//---------------------------------------------------------------------------

#include <vcl.h>
#include <windows.h>
#pragma hdrstop
//---------------------------------------------------------------------------
//   Important note about DLL memory management when your DLL uses the
//   static version of the RunTime Library:
//
//   If your DLL exports any functions that pass String objects (or structs/
//   classes containing nested Strings) as parameter or function results,
//   you will need to add the library MEMMGR.LIB to both the DLL project and
//   any other projects that use the DLL.  You will also need to use MEMMGR.LIB
//   if any other projects which use the DLL will be performing new or delete
//   operations on any non-TObject-derived classes which are exported from the
//   DLL. Adding MEMMGR.LIB to your project will change the DLL and its calling
//   EXE's to use the BORLNDMM.DLL as their memory manager.  In these cases,
//   the file BORLNDMM.DLL should be deployed along with your DLL.
//
//   To avoid using BORLNDMM.DLL, pass string information using "char *" or
//   ShortString parameters.
//
//   If your DLL uses the dynamic version of the RTL, you do not need to
//   explicitly add MEMMGR.LIB as this will be done implicitly for you
//---------------------------------------------------------------------------

#define PLUGIN_NAME        "Basic Sample Plug-in"
#define PLUGIN_DESCRIPTION PLUGIN_NAME " (Mozilla SDK)"
#define PLUGIN_VERSION     "1.0.0.0"

#define NPERR_BASE                         0
#define NPERR_NO_ERROR                    (NPERR_BASE + 0)
#define NPERR_GENERIC_ERROR               (NPERR_BASE + 1)
#define NPERR_INVALID_INSTANCE_ERROR      (NPERR_BASE + 2)
#define NPERR_INVALID_FUNCTABLE_ERROR     (NPERR_BASE + 3)
#define NPERR_MODULE_LOAD_FAILED_ERROR    (NPERR_BASE + 4)
#define NPERR_OUT_OF_MEMORY_ERROR         (NPERR_BASE + 5)
#define NPERR_INVALID_PLUGIN_ERROR        (NPERR_BASE + 6)
#define NPERR_INVALID_PLUGIN_DIR_ERROR    (NPERR_BASE + 7)
#define NPERR_INCOMPATIBLE_VERSION_ERROR  (NPERR_BASE + 8)
#define NPERR_INVALID_PARAM               (NPERR_BASE + 9)
#define NPERR_INVALID_URL                 (NPERR_BASE + 10)
#define NPERR_FILE_NOT_FOUND              (NPERR_BASE + 11)
#define NPERR_NO_DATA                     (NPERR_BASE + 12)
#define NPERR_STREAM_NOT_SEEKABLE         (NPERR_BASE + 13)
#define NPERR_TIME_RANGE_NOT_SUPPORTED    (NPERR_BASE + 14)
#define NPERR_MALFORMED_SITE              (NPERR_BASE + 15)

#include "nptypes.h"
//#include "npapi.h"
//#include "npfunctions.h"
//#include "npruntime.h"

typedef struct
{
    uint16_t size;
    uint16_t version;
    void*    ptr[55];
} NPNetscapeFuncs;

typedef struct
{
    uint16_t size;
    uint16_t version;
    void*    ptr[19];
} NPPluginFuncs;

typedef unsigned char NPBool;
typedef int16_t       NPError;
typedef int16_t       NPReason;
typedef char*         NPMIMEType;

typedef struct _NPP
{
  void* pdata;      /* plug-in private data */
  void* ndata;      /* netscape private data */
} NPP_t;

typedef NPP_t*  NPP;

typedef struct _NPRect
{
  uint16_t top;
  uint16_t left;
  uint16_t bottom;
  uint16_t right;
} NPRect;

typedef enum {
  NPWindowTypeWindow = 1,
  NPWindowTypeDrawable
} NPWindowType;

typedef struct _NPWindow
{
  void* window;  /* Platform specific window handle */
                 /* OS/2: x - Position of bottom left corner */
                 /* OS/2: y - relative to visible netscape window */
  int32_t  x;      /* Position of top left corner relative */
  int32_t  y;      /* to a netscape page. */
  uint32_t width;  /* Maximum window size */
  uint32_t height;
  NPRect   clipRect; /* Clipping rectangle in port coordinates */
  NPWindowType type; /* Is this a window or a drawable? */
} NPWindow;

typedef struct _NPSavedData
{
  int32_t len;
  void*   buf;
} NPSavedData;

typedef struct _NPStream
{
  void*    pdata; /* plug-in private data */
  void*    ndata; /* netscape private data */
  const    char* url;
  uint32_t end;
  uint32_t lastmodified;
  void*    notifyData;
  const    char* headers; /* Response headers from host.
                           * Exists only for >= NPVERS_HAS_RESPONSE_HEADERS.
                           * Used for HTTP only; NULL for non-HTTP.
                           * Available from NPP_NewStream onwards.
                           * Plugin should copy this data before storing it.
                           * Includes HTTP status line and all headers,
                           * preferably verbatim as received from server,
                           * headers formatted as in HTTP ("Header: Value"),
                           * and newlines (\n, NOT \r\n) separating lines.
                           * Terminated by \n\0 (NOT \n\n\0). */
} NPStream;

typedef struct _NPFullPrint
{
  NPBool pluginPrinted;/* Set TRUE if plugin handled fullscreen printing */
  NPBool printOne;     /* TRUE if plugin should print one copy to default
                          printer */
  void* platformPrint; /* Platform-specific printing info */
} NPFullPrint;

typedef struct _NPEmbedPrint
{
  NPWindow window;
  void* platformPrint; /* Platform-specific printing info */
} NPEmbedPrint;

typedef struct _NPPrint
{
  uint16_t mode;               /* NP_FULL or NP_EMBED */
  union
  {
    NPFullPrint fullPrint;   /* if mode is NP_FULL */
    NPEmbedPrint embedPrint; /* if mode is NP_EMBED */
  } print;
} NPPrint;

typedef enum {
  NPPVpluginNameString = 1,
  NPPVpluginDescriptionString,
  NPPVpluginWindowBool,
  NPPVpluginTransparentBool,
  NPPVjavaClass,
  NPPVpluginWindowSize,
  NPPVpluginTimerInterval,
  NPPVpluginScriptableInstance = (10),
  NPPVpluginScriptableIID = 11,
  NPPVjavascriptPushCallerBool = 12,
  NPPVpluginKeepLibraryInMemory = 13,
  NPPVpluginNeedsXEmbed         = 14,

  /* Get the NPObject for scripting the plugin. Introduced in NPAPI minor version 14.
   */
  NPPVpluginScriptableNPObject  = 15,

  /* Get the plugin value (as \0-terminated UTF-8 string data) for
   * form submission if the plugin is part of a form. Use
   * NPN_MemAlloc() to allocate memory for the string data. Introduced
   * in NPAPI minor version 15.
   */
  NPPVformValue = 16,

  NPPVpluginUrlRequestsDisplayedBool = 17,

  /* Checks if the plugin is interested in receiving the http body of
   * all http requests (including failed ones, http status != 200).
   */
  NPPVpluginWantsAllNetworkStreams = 18,

  /* Browsers can retrieve a native ATK accessibility plug ID via this variable. */
  NPPVpluginNativeAccessibleAtkPlugId = 19,

  /* Checks to see if the plug-in would like the browser to load the "src" attribute. */
  NPPVpluginCancelSrcStream = 20,

  NPPVSupportsAdvancedKeyHandling = 21
} NPPVariable;

typedef enum {
  NPNVxDisplay = 1,
  NPNVxtAppContext,
  NPNVnetscapeWindow,
  NPNVjavascriptEnabledBool,
  NPNVasdEnabledBool,
  NPNVisOfflineBool,

  NPNVserviceManager = (10),
  NPNVDOMElement     = (11),
  NPNVDOMWindow      = (12),
  NPNVToolkit        = (13),
  NPNVSupportsXEmbedBool = 14,

  /* Get the NPObject wrapper for the browser window. */
  NPNVWindowNPObject = 15,

  /* Get the NPObject wrapper for the plugins DOM element. */
  NPNVPluginElementNPObject = 16,

  NPNVSupportsWindowless = 17,

  NPNVprivateModeBool = 18,

  NPNVsupportsAdvancedKeyHandling = 21

#if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
  , NPNVSupportsWindowlessLocal = 2002
#endif
} NPNVariable;

extern "C" __declspec(dllexport) WINAPI NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved);
extern "C" __declspec(dllexport) WINAPI NPError NPP_Destroy(NPP instance, NPSavedData** save);
extern "C" __declspec(dllexport) WINAPI NPError NPP_SetWindow(NPP instance, NPWindow* window);
extern "C" __declspec(dllexport) WINAPI NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16_t* stype);
extern "C" __declspec(dllexport) WINAPI NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason);
extern "C" __declspec(dllexport) WINAPI int32_t NPP_WriteReady(NPP instance, NPStream* stream);
extern "C" __declspec(dllexport) WINAPI int32_t NPP_Write(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buffer);
extern "C" __declspec(dllexport) WINAPI void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname);
extern "C" __declspec(dllexport) WINAPI void NPP_Print(NPP instance, NPPrint* platformPrint);
extern "C" __declspec(dllexport) WINAPI int16_t NPP_HandleEvent(NPP instance, void* event);
extern "C" __declspec(dllexport) WINAPI void NPP_URLNotify(NPP instance, const char* URL, NPReason reason, void* notifyData);
extern "C" __declspec(dllexport) WINAPI NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value);
extern "C" __declspec(dllexport) WINAPI NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value);




static NPNetscapeFuncs* sBrowserFuncs = NULL;

typedef struct InstanceData {
  NPP npp;
  NPWindow window;
} InstanceData;


#pragma argsused
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved)
{
    return 1;
}
//---------------------------------------------------------------------------
extern "C" __declspec(dllexport) WINAPI NPError
NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs)
{
    sBrowserFuncs = bFuncs;

    if (pFuncs->size < 19*sizeof(void*) + sizeof(void*))
        return NPERR_INVALID_FUNCTABLE_ERROR;

  pFuncs->ptr[0]= NPP_New;
  pFuncs->ptr[1]= NPP_Destroy;
  pFuncs->ptr[2]= NPP_SetWindow;
  pFuncs->ptr[3]= NPP_NewStream;
  pFuncs->ptr[4]= NPP_DestroyStream;
  pFuncs->ptr[5]= NPP_StreamAsFile;
  pFuncs->ptr[6]= NPP_WriteReady;
  pFuncs->ptr[7]= NPP_Write;
  pFuncs->ptr[8]= NPP_Print;
  pFuncs->ptr[9]= NPP_HandleEvent;
  pFuncs->ptr[10]= NPP_URLNotify;
  pFuncs->ptr[12]= NPP_GetValue;
  pFuncs->ptr[13]= NPP_SetValue;

  return NPERR_NO_ERROR;
}

extern "C" __declspec(dllexport) WINAPI char* NP_GetPluginVersion(void)
{
  return PLUGIN_VERSION;
}

extern "C" __declspec(dllexport) WINAPI char*
NP_GetMIMEDescription()
{
  return "application/xftp-app";
}

extern "C" __declspec(dllexport) WINAPI NPError
NP_GetValue(void* future, NPPVariable aVariable, void* aValue) {
  switch (aVariable) {
    case NPPVpluginNameString:
      *((char**)aValue) = PLUGIN_NAME;
      break;
    case NPPVpluginDescriptionString:
      *((char**)aValue) = PLUGIN_DESCRIPTION;
      break;
    default:
      return NPERR_INVALID_PARAM;
      break;
  }
  return NPERR_NO_ERROR;
}

extern "C" __declspec(dllexport) WINAPI NPError
NP_Shutdown()
{
  return NPERR_NO_ERROR;
}

extern "C" __declspec(dllexport) WINAPI NPError
NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved) {
  // Make sure we can render this plugin
  NPBool browserSupportsWindowless = false;
  sBrowserFuncs->getvalue(instance, NPNVSupportsWindowless, &browserSupportsWindowless);
  if (!browserSupportsWindowless) {
    printf("Windowless mode not supported by the browser\n");
    return NPERR_GENERIC_ERROR;
  }

  sBrowserFuncs->setvalue(instance, NPPVpluginWindowBool, (void*)false);

  // set up our our instance data
  InstanceData* instanceData = (InstanceData*)malloc(sizeof(InstanceData));
  if (!instanceData)
    return NPERR_OUT_OF_MEMORY_ERROR;
  memset(instanceData, 0, sizeof(InstanceData));
  instanceData->npp = instance;
  instance->pdata = instanceData;

  return NPERR_NO_ERROR;
}

extern "C" __declspec(dllexport) WINAPI NPError
NPP_Destroy(NPP instance, NPSavedData** save) {
  InstanceData* instanceData = (InstanceData*)(instance->pdata);
  free(instanceData);
  return NPERR_NO_ERROR;
}

extern "C" __declspec(dllexport) WINAPI NPError
NPP_SetWindow(NPP instance, NPWindow* window) {
  InstanceData* instanceData = (InstanceData*)(instance->pdata);
  instanceData->window = *window;
  return NPERR_NO_ERROR;
}

extern "C" __declspec(dllexport) WINAPI NPError
NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16_t* stype) {
  return NPERR_GENERIC_ERROR;
}

extern "C" __declspec(dllexport) WINAPI NPError
NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason) {
  return NPERR_GENERIC_ERROR;
}

extern "C" __declspec(dllexport) WINAPI int32_t
NPP_WriteReady(NPP instance, NPStream* stream) {
  return 0;
}

extern "C" __declspec(dllexport) WINAPI int32_t
NPP_Write(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buffer) {
  return 0;
}

extern "C" __declspec(dllexport) WINAPI void
NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname) {

}

extern "C" __declspec(dllexport) WINAPI void
NPP_Print(NPP instance, NPPrint* platformPrint) {

}

extern "C" __declspec(dllexport) WINAPI int16_t
NPP_HandleEvent(NPP instance, void* event) {
/*  InstanceData *instanceData = (InstanceData*)(instance->pdata);
  XEvent *nativeEvent = (XEvent*)event;

  if (nativeEvent->type != GraphicsExpose)
    return 0;

  XGraphicsExposeEvent *expose = &nativeEvent->xgraphicsexpose;
  instanceData->window.window = (void*)(expose->drawable);

  GdkNativeWindow nativeWinId = (XID)(instanceData->window.window);
  GdkDrawable* gdkWindow = GDK_DRAWABLE(gdk_window_foreign_new(nativeWinId));
  drawWindow(instanceData, gdkWindow);
  g_object_unref(gdkWindow);
  */
  return 0;//1;
}

extern "C" __declspec(dllexport) WINAPI void
NPP_URLNotify(NPP instance, const char* URL, NPReason reason, void* notifyData) {

}

extern "C" __declspec(dllexport) WINAPI NPError
NPP_GetValue(NPP instance, NPPVariable variable, void *value) {
  return NPERR_GENERIC_ERROR;
}

extern "C" __declspec(dllexport) WINAPI NPError
NPP_SetValue(NPP instance, NPNVariable variable, void *value) {
  return NPERR_GENERIC_ERROR;
}